package com.yoga.manager.app.impl;

import com.yoga.common.appexception.AppErrorCodeEnum;
import com.yoga.common.appexception.AppException;
import com.yoga.common.bo.AboutClassRecordBO;
import com.yoga.common.bo.ClassBO;
import com.yoga.common.bo.ClassTableBO;
import com.yoga.common.bo.CourseBO;
import com.yoga.common.page.PageBO;
import com.yoga.common.qto.AboutClassRecordQTO;
import com.yoga.common.qto.ClassTableQTO;
import com.yoga.common.qto.CourseQTO;
import com.yoga.dao.dao.AboutClassRecordDao;
import com.yoga.dao.dao.ClassTableDao;
import com.yoga.dao.dao.CourseDao;
import com.yoga.dao.domain.ClassTableDO;
import com.yoga.manager.app.AppClassTableManager;
import com.yoga.manager.app.AppPlainVipManager;
import com.yoga.manager.app.AppPrivateVipManager;
import com.yoga.manager.beanUtil.AboutClassRecordBeanUtil;
import com.yoga.manager.beanUtil.ClassTableBeanUtil;
import com.yoga.manager.beanUtil.CourseBeanUtil;
import com.yoga.manager.uitl.DateStyle;
import com.yoga.manager.uitl.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Created by hdx on 2020/9/27.
 */
@Component
public class AppClassTableManagerImpl implements AppClassTableManager {
    Logger logger = LoggerFactory.getLogger(AppClassTableManagerImpl.class);

    @Resource
    private ClassTableDao classTableDao;

    @Resource
    private CourseDao courseDao;

    @Resource
    private AboutClassRecordDao aboutClassRecordDao;

    @Resource
    private AppPlainVipManager appPlainVipManager;

    @Resource
    private AppPrivateVipManager appPrivateVipManager;

    @Override
    public PageBO<ClassTableBO> findForPage(ClassTableQTO classTableQTO) throws AppException {
        if (classTableQTO == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (classTableQTO.getYogaUserId() == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (classTableQTO.getYogaShopId() == null) {
            throw new AppException(AppErrorCodeEnum.NOT_SHOP_CHORES);
        }
        if (classTableQTO.getClassType() == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (classTableQTO.getClassType() != 1 && classTableQTO.getClassType() != 2) {
            throw new AppException(AppErrorCodeEnum.PARAM_ERROR);
        }
        if (classTableQTO.getClassType() == 1 && !appPlainVipManager.getIsPlainVIP(classTableQTO.getYogaUserId())) {
            throw new AppException(AppErrorCodeEnum.NOT_ABOUT_NULL);
        }
        if (classTableQTO.getClassType() == 2 && !appPrivateVipManager.getIsPrivateVIP(classTableQTO.getYogaUserId())) {
            throw new AppException(AppErrorCodeEnum.NOT_ABOUT_NULL);
        }
        Date today = DateUtil.dateFormat(new Date(), DateStyle.YYYY_MM_DD);
        if (classTableQTO.getClassDate() == null) {
            classTableQTO.setClassDate(today);
        }
        if (classTableQTO.getClassDate() != null) {
            classTableQTO.setClassDate(DateUtil.dateFormat(classTableQTO.getClassDate(), DateStyle.YYYY_MM_DD));
        }
        if (classTableQTO.getClassDate().getTime() < today.getTime()) {
            throw new AppException(AppErrorCodeEnum.NOW_ABOUT_AFTER_CLASS);
        }
        PageBO<ClassTableBO> pageBO = new PageBO<>();
        pageBO.setQuery(classTableQTO);
        Integer count = classTableDao.findForPageCount(classTableQTO);
        if (count == null || count <= 0) {
            return pageBO;
        }
        List<ClassTableBO> boList = ClassTableBeanUtil.doList2BOList(classTableDao.findForPage(classTableQTO));
        if (!CollectionUtils.isEmpty(boList)) {
            boList = signStatus(boList, classTableQTO.getYogaUserId());
        }
//        Map<Date, List<ClassTableBO>> map = boList.stream().collect(Collectors.groupingBy(ClassTableBO::getClassDate));
        pageBO.setTotalCount(count);
        pageBO.setData(boList);

        return pageBO;
    }


    @Override
    public List<ClassBO> findWeekClassTable(ClassTableQTO classTableQTO) throws AppException {
        if (classTableQTO == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (classTableQTO.getYogaUserId() == null) {
            throw new AppException(AppErrorCodeEnum.YOGA_USER_ID_NULL);
        }
        if (classTableQTO.getYogaShopId() == null) {
            throw new AppException(AppErrorCodeEnum.NOT_CHOICE_SHOP);
        }
        if (classTableQTO.getClassType() == null || (classTableQTO.getClassType() != 1 && classTableQTO.getClassType() != 2)) {
            throw new AppException(AppErrorCodeEnum.PARAM_ERROR);
        }
        if (classTableQTO.getClassType() == 1) {
            if (!appPlainVipManager.getIsPlainVIP(classTableQTO.getYogaUserId())) {
                throw new AppException(AppErrorCodeEnum.NOT_ABOUT_NULL);
            }
        } else if (classTableQTO.getClassType() == 2) {
            if (!appPrivateVipManager.getIsPrivateVIP(classTableQTO.getYogaUserId())) {
                throw new AppException(AppErrorCodeEnum.NOT_ABOUT_NULL);
            }
        }
        if (classTableQTO.getWeekType() == 0) {
            classTableQTO.setStartDate(DateUtil.getThisWeekMonday());
            classTableQTO.setEndDate(DateUtil.getThisWeekSunday());
        } else if (classTableQTO.getWeekType() == 1) {
            classTableQTO.setStartDate(DateUtil.getNextWeekMonday());
            classTableQTO.setEndDate(DateUtil.getNextWeekSunday());
        }
        classTableQTO.setNeedPaging(false);
        List<ClassTableBO> boList = ClassTableBeanUtil.doList2BOList(classTableDao.findForPage(classTableQTO));
        List<ClassBO> result = new ArrayList<>();
        if (CollectionUtils.isEmpty(boList)) {
            return result;
        }
        boList = signStatus(boList, classTableQTO.getYogaUserId());

        Map<Date, List<ClassTableBO>> map = boList.stream().collect(Collectors.groupingBy(ClassTableBO::getClassDate));
        for (Map.Entry<Date, List<ClassTableBO>> entry : map.entrySet()) {
            ClassBO classBO = new ClassBO();
            classBO.setDayDate(entry.getKey());
            classBO.setClassTableBOs(entry.getValue());
            result.add(classBO);
        }

        return result;
    }


    private List<ClassTableBO> signStatus(List<ClassTableBO> boList, Long yogaUserId) {
        boList.stream().forEach(classTableBO -> classTableBO.setClassStatus(0));

        Date nowTime = DateUtil.dateFormat(new Date(), DateStyle.HH_MM);
        boList.stream().filter(classTableBO -> DateUtil.addHour(classTableBO.getStartTime(), -1).getTime() < nowTime.getTime())
                .forEach(classTableBO -> classTableBO.setClassStatus(2));//设为已开课，开课前30分钟不能预约

        List<Long> courseIds = new ArrayList<>(boList.stream().map(ClassTableBO::getCourseId).collect(Collectors.toSet()));
        if (!CollectionUtils.isEmpty(courseIds)) {
            CourseQTO courseQTO = new CourseQTO();
            courseQTO.setCourseIds(courseIds);
            courseQTO.setNeedPaging(false);
            List<CourseBO> courseBOs = CourseBeanUtil.doList2BOList(courseDao.findForPage(courseQTO));
            if (!CollectionUtils.isEmpty(courseBOs)) {
                Map<Long, CourseBO> courseBOMap = courseBOs.stream().collect(Collectors.toMap(CourseBO::getCourseId, Function.identity()));
                if (!CollectionUtils.isEmpty(courseBOMap)) {
                    boList.stream().filter(classTableBO -> classTableBO.getCourseId() != null && courseBOMap.containsKey(classTableBO.getCourseId()))
                            .forEach(classTableBO -> classTableBO.setCourseBO(courseBOMap.get(classTableBO.getCourseId())));
                }
            }
        }
        List<Long> classTableIds = new ArrayList<>(boList.stream().map(ClassTableBO::getClassTableId).collect(Collectors.toSet()));
        if (!CollectionUtils.isEmpty(classTableIds)) {
            AboutClassRecordQTO recordQTO = new AboutClassRecordQTO();
            recordQTO.setClassTableIds(classTableIds);
            recordQTO.setYogaUserId(yogaUserId);
            recordQTO.setNeedPaging(false);
            List<AboutClassRecordBO> recordBOs = AboutClassRecordBeanUtil.doList2BOList(aboutClassRecordDao.findForPage(recordQTO));
            recordBOs.stream().filter(aboutClassRecordBO -> aboutClassRecordBO.getRecordStatus() == 2).forEach(aboutClassRecordBO -> recordBOs.remove(this));
            if (!CollectionUtils.isEmpty(recordBOs)) {
                Map<Long, AboutClassRecordBO> recordBOMap = recordBOs.stream().collect(Collectors.toMap(AboutClassRecordBO::getClassTableId, Function.identity()));
                if (!CollectionUtils.isEmpty(recordBOMap)) {
                    boList.stream().filter(classTableBO -> recordBOMap.containsKey(classTableBO.getClassTableId()))
                            .forEach(classTableBO -> classTableBO.setClassStatus(1));
                }
            }
        }
        return boList;
    }

    @Override
    public List<ClassTableBO> findByIds(List<Long> classTableIds) throws AppException {
        if (CollectionUtils.isEmpty(classTableIds)) {
            return new ArrayList<>();
        }
        List<ClassTableDO> doList = classTableDao.findByIds(classTableIds);
        List<ClassTableBO> boList = ClassTableBeanUtil.doList2BOList(doList);
        List<Long> courseIds = new ArrayList<>(doList.stream().map(ClassTableDO::getCourseId).collect(Collectors.toSet()));
        if (!CollectionUtils.isEmpty(courseIds)) {
            CourseQTO courseQTO = new CourseQTO();
            courseQTO.setCourseIds(courseIds);
            courseQTO.setNeedPaging(false);
            List<CourseBO> courseBOs = CourseBeanUtil.doList2BOList(courseDao.findForPage(courseQTO));
            if (!CollectionUtils.isEmpty(courseBOs)) {
                Map<Long, CourseBO> courseBOMap = courseBOs.stream().collect(Collectors.toMap(CourseBO::getCourseId, Function.identity()));
                if (!CollectionUtils.isEmpty(courseBOMap)) {
                    boList.stream().filter(classTableBO -> classTableBO.getCourseId() != null && courseBOMap.containsKey(classTableBO.getCourseId()))
                            .forEach(classTableBO -> classTableBO.setCourseBO(courseBOMap.get(classTableBO.getCourseId())));
                }
            }
        }


        return boList;
    }
}
